#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include "Wrappers/UnixUtils/NamedPipe.hpp"
#include "Wrappers/UnixUtils/Tests/NamedPipe_tests.hpp"

namespace wrappers {
namespace unix_utils {

NamedPipe_tests::NamedPipe_tests()
: mTestRunner("Named pipes (FIFO)'s tests")
{
  /*mTestRunner.AddTestCase(
      UTESTS_MAKE_CASE_DATA(NamedPipe_tests::NonTemplatedFunctions));*/
  mTestRunner.AddTestCase(
      UTESTS_MAKE_CASE_DATA(NamedPipe_tests::TemplatedFunctions));
  mTestRunner.AddTestCase(
      UTESTS_MAKE_CASE_DATA(NamedPipe_tests::AllFunctionsWithThread));
  mTestRunner.Run(true);
}

NamedPipe_tests::~NamedPipe_tests()
{

}
UTESTS_START_TEST(NamedPipe_tests::NonTemplatedFunctions) {
  /*NamedPipe pipe("/tmp/plazza_unittesting_tmpfifo_0");

  pipe.Write(std::string("Allo ? Non mais allo quoi\n"));
  std::string data0 = pipe.Read();
  UTESTS_FAIL_UNLESS(data0 == "Allo ? Non mais allo quoi",
      "non-templated failed");*/
}
UTESTS_END_TEST

UTESTS_START_TEST(NamedPipe_tests::TemplatedFunctions) {
  NamedPipe pipe("/tmp/plazza_unittesting_tmpfifo_1");

  pipe.Write("T'es un FIFO et tu recois rien ?\n", 34);
  pipe.Write<char>("Allo ? Allo ? J'che pas vous me recevez ?\n", 43);
  std::string str(
      "C'est comme si je te dis t'es a EPITECH t'as pas de wifi\n");
  NamedPipe_testsData data = { 123, 456 };
  pipe.Write<NamedPipe_testsData>(&data, sizeof(data));

  char data1[35] = { 0 };
  std::string res = pipe.Read<char>(&data1[0], 34);
  UTESTS_FAIL_UNLESS(res == "T'es un FIFO et tu recois rien ?\n",
      "templated<char> 1 failed");

  char data2[43] = { 0 };
  pipe.Read<char>(&data2[0], 43);
  UTESTS_FAIL_UNLESS(std::string(&data2[0])
  == "Allo ? Allo ? J'che pas vous me recevez ?\n",
  "templated<char> 2 failed");

  NamedPipe_testsData data3;
  pipe.Read<NamedPipe_testsData>(&data3, sizeof(data3));
  UTESTS_FAIL_UNLESS(data3.magic1 == 123 && data3.magic2 == 456,
      "templated<struct> failed");
}
UTESTS_END_TEST

UTESTS_START_TEST(NamedPipe_tests::AllFunctionsWithThread) {
  NamedPipe pipe("/tmp/plazza_unittesting_tmpfifo_2");
  pthread_t thread;

  pthread_create(&thread, NULL, NamedPipe_tests::ThreadTimedLocker, &pipe);
  usleep(100);
  char data1[35] = { 0 };
  std::string res = pipe.Read<char>(&data1[0], 34);
  UTESTS_FAIL_UNLESS(res == "T'es un FIFO et tu recois rien ?\n",
      "templated<char> 1 failed");
  char data2[43] = { 0 };
  pipe.Read<char>(&data2[0], 43);
  UTESTS_FAIL_UNLESS(std::string(&data2[0])
  == "Allo ? Allo ? J'che pas vous me recevez ?\n",
  "templated<char> 2 failed");

  NamedPipe_testsData data3;
  pipe.Read<NamedPipe_testsData>(&data3, sizeof(data3));
  UTESTS_FAIL_UNLESS(data3.magic1 == 123 && data3.magic2 == 456,
      "templated<struct> failed");
}
UTESTS_END_TEST

void *NamedPipe_tests::ThreadTimedLocker(void *args) {
  NamedPipe_testsData data = { 123, 456 };

  NamedPipe pipe(
      *(NamedPipe *) (args)); // using
  pipe.Write("T'es un FIFO et tu recois rien ?\n", 34);
  pipe.Write<char>("Allo ? Allo ? J'che pas vous me recevez ?\n", 43);
  pipe.Write<NamedPipe_testsData>(&data, sizeof(data));
  sleep(100);
  return NULL;
}

} /* namespace unix_utils */
} /* namespace wrappers */
